package com.cwx.mychat.openai.service;

import com.cwx.mychat.entity.constant.CodeConstant;
import com.cwx.mychat.entity.constant.SysSettingConstant;
import com.cwx.mychat.entity.dto.TokenUserInfoDto;
import com.cwx.mychat.entity.enums.ExceptionBizCodeEnum;
import com.cwx.mychat.entity.enums.MessageStatusEnum;
import com.cwx.mychat.entity.enums.MessageTypeEnum;
import com.cwx.mychat.entity.enums.UserContactTypeEnum;
import com.cwx.mychat.entity.po.ChatMessage;
import com.cwx.mychat.entity.po.ChatSession;
import com.cwx.mychat.entity.vo.MessageSendVo;
import com.cwx.mychat.exception.BusinessException;
import com.cwx.mychat.service.ChatMessageService;
import com.cwx.mychat.service.ChatSessionService;
import com.cwx.mychat.utils.R;
import com.cwx.mychat.utils.cipher.AESUtils;
import com.cwx.mychat.utils.common.CommonUtil;
import com.cwx.mychat.utils.redis.RedisComponent;
import com.cwx.mychat.utils.stringUtils.StringUtil;
import com.cwx.mychat.websocket.context.ChannelContextUtil;
import com.cwx.mychat.websocket.message.SendMessageHandler;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.Disposable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 作者： cwx
 * 时间： 2025/1/2 10:45
 * 版本： 1.0
 * 注释：处理消息并发送消息
 */
@Service
@Slf4j
public class AIChatSendMessage {

    @Resource
    private RedisComponent redisComponent;

    @Resource
    private AIChatAssistantService aiChatAssistantService;

    @Resource
    private ChatSessionService chatSessionService;

    @Resource
    private ChatMessageService chatMessageService;

    @Autowired
    private SendMessageHandler sendMessageHandler;

    //记录message中的特殊字符
    private final Map<String, Object> recordMessage = new HashMap<>();

    //记录什么
    private String codeLanguage = "";
    //关键字
    private final String keyword = "code";
    //暂存message
    private final StringBuilder messageBuilder = new StringBuilder();

    //中断参数初始化
    AtomicBoolean shouldStop = new AtomicBoolean(false);

    /**
     * 机器人发送消息,通过websocket返回消息
     * @return
     */
    @Transactional
    public void sendMessage(ChatMessage chatMessage, TokenUserInfoDto tokenUserInfoDto, SysSettingConstant sysSetting) {
        //初始化中断处理参数
        shouldStop.set(false);
        //判断流有没有结束
        //初始化字符
        messageBuilder.delete(0, messageBuilder.length());
        recordMessage.clear();
        ChatMessage robotMessage = setRobotMessage(tokenUserInfoDto, sysSetting);;
        chatMessage.setStatus(MessageStatusEnum.SENDING.getStatus());
        MessageSendVo messageSendVo = new MessageSendVo();
        BeanUtils.copyProperties(robotMessage, messageSendVo);
        StringBuilder stringBuilder = new StringBuilder();
        //实现聊天对接
        aiChatAssistantService.assistant(chatMessage.getMessageContent(), tokenUserInfoDto, chatMessage.getSessionId())
                .doOnNext(message -> {
                    if(shouldStop.get()){
                        //中断处理，将剩余消息保存并发送
                        resultSendMessage(chatMessage, robotMessage, messageSendVo, stringBuilder);
                        //将中断参数恢复
                        shouldStop.set(false);
                        throw new RuntimeException("中断处理");
                    }
                    String msg = StringUtil.cleanSlash(message);
                    if("```".contains(msg)){
                        messageBuilder.append(msg);
                    }
                    if(recordMessage.containsKey("```") && CodeConstant.CODE_LANGUAGE.contains(msg.toLowerCase())){
                        recordMessage.put(keyword, 1);
                        codeLanguage = message;
                        recordMessage.remove("```");
                    }
                    if(messageBuilder.toString().equals("```")){
                        //清理messageBuilder
                        messageBuilder.delete(0, messageBuilder.length());
                        if(!recordMessage.containsKey(keyword)){
                            recordMessage.put("```", 1);
                        }
                        //判断哪种代码
                        if(recordMessage.containsKey(keyword) && recordMessage.get(keyword).equals(2)){
                            recordMessage.put(keyword, 3);
                        }
                    }
                })
                .subscribe(message -> {
                    //通过webSocket发送消息
                    if(message.equals(CodeConstant.STREAM_END)){
                        //结束操作
                        resultSendMessage(chatMessage, robotMessage, messageSendVo, stringBuilder);
                    }else{
                        //重新构建message
                        String newMessage = rebuildMessage(message);
                        //判断message是否带有换行符
                        messageSendVo.setMessageContent(newMessage);
                        stringBuilder.append(newMessage);
                        sendMessageHandler.sendSyncMessage(messageSendVo);
                    }
                });

    }

    /**
     * 最终发送消息
     * @param chatMessage
     * @param robotMessage
     * @param messageSendVo
     * @param stringBuilder
     */
    private void resultSendMessage(ChatMessage chatMessage, ChatMessage robotMessage, MessageSendVo messageSendVo, StringBuilder stringBuilder) {
        messageSendVo.setMessageType(chatMessage.getMessageType());
        robotMessage.setCreateTime(new Date());
        robotMessage.setMessageType(chatMessage.getMessageType());
        robotMessage.setStatus(MessageStatusEnum.SEND.getStatus());
        //对消息进行后处理
        robotMessage.setMessageContent(messagePostProcessService(stringBuilder));
        boolean save = chatMessageService.save(robotMessage);
        try{
            messageSendVo.setMessageContent(AESUtils.decryptLargeData(robotMessage.getMessageContent()));
        }catch (Exception e){
            log.error("解密失败，使用密文发送");
            messageSendVo.setMessageContent("抱歉，消息解密失败，请联系管理员！");
        }
        messageSendVo.setMessageId(robotMessage.getMessageId().toString());
        if(save) sendMessageHandler.sendSyncMessage(messageSendVo);
    }

    //消息后处理操作
    private String messagePostProcessService(StringBuilder stringBuilder) {
        //判断消息中是否存在地址
        String messageContent = stringBuilder.toString();
        if(StringUtil.containUrl(messageContent)){
            messageContent = StringUtil.convertUrlsToLinks(messageContent);
        }
        //对消息进行加密处理
        if(!StringUtil.isEmpty(stringBuilder.toString())){
            try {
               messageContent = AESUtils.encryptLargeData(messageContent);
            } catch (Exception e) {
                log.error("加密失败，使用明文储存");
            }
        }
        return messageContent;
    }

    private String rebuildMessage(String message) {
//        log.info("message:{}, 是否为空：{}", recordMessage, recordMessage.isEmpty());
        String msg = StringUtil.cleanSlash(message);
        if(!recordMessage.isEmpty()){
            if("```".contains(msg)){
                //将message设置为空字符串
                message = "";
            }
            if(recordMessage.containsKey(keyword) && recordMessage.get(keyword).equals(1)){
                //组装html
                message = String.format(CodeConstant.CODE_LANGUAGE_PREFIX, codeLanguage, codeLanguage.toLowerCase());
                recordMessage.put(keyword, 2);
                return message;
            }
            if(recordMessage.containsKey(keyword) && recordMessage.get(keyword).equals(2)){
                if(message.contains("<") || message.contains(">")){
                    return StringUtil.cleanHtmlDayuXiaoyu(message);
                }
                return message;
            }
            if(recordMessage.containsKey(keyword) && recordMessage.get(keyword).equals(3)){
                recordMessage.remove(keyword);
                return CodeConstant.CODE_LANGUAGE_SUFFIX;
            }
        }
        return StringUtil.cleanHtmlTag(message);
    }

    //设置robotMessage基本参数
    private ChatMessage setRobotMessage(TokenUserInfoDto tokenUserInfoDto, SysSettingConstant sysSetting) {
        ChatMessage robotMessage = new ChatMessage();
        robotMessage.setMessageType(MessageTypeEnum.CHAT.getType());
        robotMessage.setContactId(tokenUserInfoDto.getUserId());
        robotMessage.setContactType(UserContactTypeEnum.USER.getType());
        robotMessage.setMessageType(MessageTypeEnum.STREAM_MESSAGE.getType());
        robotMessage.setSendUserId(sysSetting.getRobotUid());
        robotMessage.setSendUserNickName(sysSetting.getRobotNickName());
        robotMessage.setSendTime(new Date().getTime());
        robotMessage.setSessionId(CommonUtil.getChatSessionIdUser(new String[]{tokenUserInfoDto.getUserId(), sysSetting.getRobotUid()}));
        return robotMessage;
    }

    /**
     * 返回流数据
     * @param chatMessage
     * @return
     */
    @Transactional
    public Flux<String> sendMessage(ChatMessage chatMessage) throws BusinessException {
        TokenUserInfoDto securityContext = CommonUtil.getSecurityContext();
        //判断是否是机器人
        SysSettingConstant sysSetting = redisComponent.getSysSetting();
        if(!sysSetting.getRobotUid().equals(chatMessage.getContactId())){
            throw new BusinessException(ExceptionBizCodeEnum.ROBOT_NOT_EXIST);
        }
        //保存信息
        chatMessageService.saveMessage(chatMessage, securityContext);
        //更新session
        ChatSession chatSession = chatSessionService.updateSession(chatMessage, securityContext, UserContactTypeEnum.USER);
        ChatMessage robotMessage = setRobotMessage(securityContext, sysSetting);
        MessageSendVo messageSendVo = new MessageSendVo();
        BeanUtils.copyProperties(robotMessage, messageSendVo);
        StringBuilder stringBuilder = new StringBuilder();
        //实现聊天对接
        Flux<String> assistant = aiChatAssistantService.assistant(chatMessage.getMessageContent(), securityContext, chatMessage.getSessionId());
        assistant.doOnNext(message -> {
            //通过webSocket发送消息，如果结束
            if (message.equals(CodeConstant.STREAM_END)) {
                robotMessage.setCreateTime(new Date());
                robotMessage.setMessageType(chatMessage.getMessageType());
                robotMessage.setStatus(MessageStatusEnum.SEND.getStatus());
                robotMessage.setMessageContent(StringUtil.cleanHtmlTag(stringBuilder.toString()));
                messageSendVo.setMessageType(chatMessage.getMessageType());
                messageSendVo.setMessageContent(StringUtil.cleanHtmlTag(stringBuilder.toString()));
                boolean save = chatMessageService.save(robotMessage);
                messageSendVo.setMessageId(robotMessage.getMessageId().toString());
                if (save) sendMessageHandler.sendSyncMessage(messageSendVo);
            } else {
                //判断message是否带有换行符
                messageSendVo.setMessageContent(StringUtil.cleanHtmlTag(message));
                stringBuilder.append(message);
            }
        }).doOnError(err -> {
            log.error("发送消息失败", err);
        }).then().subscribe(System.out::println);
        return assistant;
    }

    /**
     * 中断操作
     * @return
     */
    public R interrupt() {
        shouldStop.set(true);
        log.info("设置中断参数为true");
        return R.ok();
    }




}
